package dream

import (
	"encoding/json"
	"strconv"
	"strings"
)

func JsonSubObjString(s, key string) string {
	jmap := make(map[string]interface{})
	err := json.Unmarshal([]byte(s), &jmap)
	if err != nil {
		return ""
	}
	value, ok := jmap[key]
	if !ok {
		return ""
	}

	switch value.(type) {
	//case JSON:
	//	break
	case map[string]interface{}:
		break
	default:
		return ""
	}

	b, _ := json.Marshal(&value)
	return string(b)
}

type JSONS string
type JSONT = map[string]interface{}
type JSONRead struct {
	JSONT
	sDef
}

func NewJSON() map[string]interface{} {
	return make(map[string]interface{})
}
func NewJSONRead(j ...map[string]interface{}) *JSONRead {
	v := &JSONRead{}
	if len(j) > 0 {
		v.JSONT = j[0]
	}
	return v
}

func (p JSONS) S(k string) JSONS {
	return JSONS(JsonSubObjString(string(p), k))
}

/*
	func (p *JSONRead) obj(s string) JSON {
		m := map[string]interface{}(p)
		value, ok := m[s]
		if !ok {
			return make(JSON)
		}
		switch v := value.(type) {
		case JSON:
			return v
		case map[string]interface{}:
			return JSON(v)
		default:
			break
		}
		return make(JSON)
	}
*/
func (p *JSONRead) str(s string) string {
	m := map[string]interface{}(p.JSONT)
	value, ok := m[s]
	if !ok {
		return ""
	}
	switch v := value.(type) {
	case int:
		return strconv.Itoa(v)
	case float64:
		return strconv.Itoa(int(v))
	case uint8:
		return strconv.Itoa(int(v))
	case uint16:
		return strconv.Itoa(int(v))
	case uint32:
		return strconv.Itoa(int(v))
	case uint64:
		return strconv.Itoa(int(v))
	case int8:
		return strconv.Itoa(int(v))
	case int16:
		return strconv.Itoa(int(v))
	case int32:
		return strconv.Itoa(int(v))
	case int64:
		return strconv.Itoa(int(v))
	case string:
		return v
	case bool:
		if v {
			return "true"
		}
		return "false"
	default:
		break
	}
	return ""
}

func (p *JSONRead) int(s string) int {
	m := map[string]interface{}(p.JSONT)
	value, ok := m[s]
	if !ok {
		return 0
	}
	switch v := value.(type) {
	case int:
		return int(v)
	case float64:
		return int(v)
	case uint8:
		return int(v)
	case uint16:
		return int(v)
	case uint32:
		return int(v)
	case uint64:
		return int(v)
	case int8:
		return int(v)
	case int16:
		return int(v)
	case int32:
		return int(v)
	case int64:
		return int(v)
	case string:
		i, _ := strconv.Atoi(v)
		return int(i)
	case bool:
		if v {
			return 1
		}
	default:
		break
	}
	return 0
}

func (p *JSONRead) float(s string) float64 {
	m := map[string]interface{}(p.JSONT)
	value, ok := m[s]
	if !ok {
		return 0
	}
	switch v := value.(type) {
	case int:
		return float64(v)
	case float64:
		return float64(v)
	case uint8:
		return float64(v)
	case uint16:
		return float64(v)
	case uint32:
		return float64(v)
	case uint64:
		return float64(v)
	case int8:
		return float64(v)
	case int16:
		return float64(v)
	case int32:
		return float64(v)
	case int64:
		return float64(v)
	case string:
		i, _ := strconv.Atoi(v)
		return float64(i)
	case bool:
		if v {
			return 1
		}
	default:
		break
	}
	return 0
}
func elementGet(m interface{}, k []interface{}) interface{} {
	if len(k) == 0 {
		return m
	}
	var kindex uint64
	switch kv := k[0].(type) {
	case string:
		switch v := m.(type) {
		case map[string]interface{}:
			value, _ := v[kv]
			return elementGet(value, k[1:])
		default:
			return nil
		}
	case int:
		kindex = uint64(kv)
	case int8:
		kindex = uint64(kv)
	case int16:
		kindex = uint64(kv)
	case int32:
		kindex = uint64(kv)
	case int64:
		kindex = uint64(kv)
	case uint:
		kindex = uint64(kv)
	case uint8:
		kindex = uint64(kv)
	case uint16:
		kindex = uint64(kv)
	case uint32:
		kindex = uint64(kv)
	case uint64:
		kindex = uint64(kv)
	default:
		return nil
	}
	switch v := m.(type) {
	case []interface{}:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []string:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []int:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []int8:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []int16:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []int32:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []int64:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []uint:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []uint8:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []uint16:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []uint32:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []uint64:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []bool:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []float32:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []float64:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	case []map[string]interface{}:
		if kindex < uint64(len(v)) {
			return elementGet(v[kindex], k[1:])
		}
		return nil
	default:
		return nil
	}
}

/*Num 得到一个数字
 */
func (p *JSONRead) Num(s string, x ...interface{}) int64 {
	value, ok := p.JSONT[s]
	if !ok {
		return p.sDef.di
	}
	getd := elementGet(value, x)
	if getd == nil {
		return p.sDef.di
	}
	switch v := getd.(type) {
	case uint:
		return int64(v)
	case uint8:
		return int64(v)
	case uint16:
		return int64(v)
	case uint32:
		return int64(v)
	case uint64:
		return int64(v)
	case int:
		return int64(v)
	case int8:
		return int64(v)
	case int16:
		return int64(v)
	case int32:
		return int64(v)
	case int64:
		return int64(v)
	case float32:
		return int64(v)
	case float64:
		return int64(v)
	default:
		break
	}
	return p.sDef.di
}

func (p *JSONRead) NumF64(s string, x ...interface{}) float64 {
	value, ok := p.JSONT[s]
	if !ok {
		return p.sDef.df
	}
	getd := elementGet(value, x)
	if getd == nil {
		return p.sDef.df
	}
	switch v := getd.(type) {
	case uint:
		return float64(v)
	case uint8:
		return float64(v)
	case uint16:
		return float64(v)
	case uint32:
		return float64(v)
	case uint64:
		return float64(v)
	case int:
		return float64(v)
	case int8:
		return float64(v)
	case int16:
		return float64(v)
	case int32:
		return float64(v)
	case int64:
		return float64(v)
	case float32:
		return float64(v)
	case float64:
		return float64(v)
	default:
		break
	}
	return p.sDef.df
}

/*Str 得到一个字符串
 */
func (p *JSONRead) Sss(s string, x ...interface{}) string {
	value, ok := p.JSONT[s]
	if !ok {
		return p.sDef.ds
	}
	getd := elementGet(value, x)
	if getd == nil {
		return p.sDef.ds
	}
	switch v := getd.(type) {
	case string:
		return v
	default:
		break
	}
	return p.sDef.ds
}

// recursive
func elementSize(m interface{}) uint64 {
	switch v := m.(type) {
	case []interface{}:
		return uint64(len(v))
	case []string:
		return uint64(len(v))
	case []int:
		return uint64(len(v))
	case []int8:
		return uint64(len(v))
	case []int16:
		return uint64(len(v))
	case []int32:
		return uint64(len(v))
	case []int64:
		return uint64(len(v))
	case []uint:
		return uint64(len(v))
	case []uint8:
		return uint64(len(v))
	case []uint16:
		return uint64(len(v))
	case []uint32:
		return uint64(len(v))
	case []uint64:
		return uint64(len(v))
	case []bool:
		return uint64(len(v))
	case []float32:
		return uint64(len(v))
	case []float64:
		return uint64(len(v))
	case []map[string]interface{}:
		return uint64(len(v))
	default:
		return 0
	}
}

/*Size 得到数组元素的长度
 */
func (p *JSONRead) Size(s string, x ...interface{}) uint64 {
	value, ok := p.JSONT[s]
	if !ok {
		return 0
	}
	getd := elementGet(value, x)
	if getd == nil {
		return 0
	}
	switch v := getd.(type) {
	case []interface{}:
		return uint64(len(v))
	case []string:
		return uint64(len(v))
	case []int:
		return uint64(len(v))
	case []int8:
		return uint64(len(v))
	case []int16:
		return uint64(len(v))
	case []int32:
		return uint64(len(v))
	case []int64:
		return uint64(len(v))
	case []uint:
		return uint64(len(v))
	case []uint8:
		return uint64(len(v))
	case []uint16:
		return uint64(len(v))
	case []uint32:
		return uint64(len(v))
	case []uint64:
		return uint64(len(v))
	case []bool:
		return uint64(len(v))
	case []float32:
		return uint64(len(v))
	case []float64:
		return uint64(len(v))
	case []map[string]interface{}:
		return uint64(len(v))
	default:
		return 0
	}
	return 0
}

type INIT = map[string]map[string]string
type INI struct {
	INIT
	sDef
}

func (p INI) Sec(s string) map[string]string {
	if s == "" {
		s = "default"
	}
	s = strings.ToLower(s)
	m := map[string]map[string]string(p.INIT)
	value, ok := m[s]
	if !ok {
		return make(map[string]string)
	}
	return value
}

func (p INI) Str(s, k string) string {
	if s == "" {
		s = "default"
	}
	s = strings.ToLower(s)
	k = strings.ToLower(k)
	m := map[string]map[string]string(p.INIT)
	value, ok := m[s]
	if !ok {
		return p.sDef.ds
	}
	kv, ok := value[k]
	if !ok {
		return p.sDef.ds
	}
	return kv
}

func (p INI) Int(s, k string) int {
	if s == "" {
		s = "default"
	}
	s = strings.ToLower(s)
	k = strings.ToLower(k)
	m := map[string]map[string]string(p.INIT)
	value, ok := m[s]
	if !ok {
		return int(p.sDef.di)
	}
	kv, ok := value[k]
	if !ok {
		return int(p.sDef.di)
	}
	i, err := strconv.Atoi(kv)
	if err != nil {
		return int(p.sDef.di)
	}
	return i
}

func (p INI) Is(s, k string) bool {
	if s == "" {
		s = "default"
	}
	s = strings.ToLower(s)
	k = strings.ToLower(k)
	m := map[string]map[string]string(p.INIT)
	value, ok := m[s]
	if !ok {
		return p.sDef.db
	}
	kv, ok := value[k]
	if !ok {
		return p.sDef.db
	}
	if len(kv) == 0 {
		return p.sDef.db
	}
	if kv == "true" {
		return true
	}
	if kv == "false" || kv == "0" {
		return false
	}
	return true
}
